package me.landery.modules.sinco.rest;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import me.landery.annotation.AnonymousAccess;
import me.landery.annotation.Log;
import me.landery.annotation.rest.AnonymousGetMapping;
import me.landery.domain.AlipayConfig;
import me.landery.domain.vo.TradeVo;
import me.landery.exception.BadRequestException;
import me.landery.modules.sinco.domain.Recharge;
import me.landery.modules.sinco.service.RechargeService;
import me.landery.modules.sinco.service.dto.ReChargeQueryCriteria;
import me.landery.modules.system.service.UserService;
import me.landery.modules.system.service.mapstruct.UserMapper;
import me.landery.service.AliPayService;
import me.landery.utils.AliPayStatusEnum;
import me.landery.utils.AlipayUtils;
import me.landery.utils.SecurityUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author cc.w
 * @Date 2022/6/7 22:53
 * @Version 1.0
 */
@RestController
@RequiredArgsConstructor
@Api(tags = "Sinco：充值记录管理")
@RequestMapping("/sinco/recharge")
public class RechargeController {
    private final RechargeService rechargeService;
    private static final String ENTITY_NAME = "recharge";


    private final AlipayUtils alipayUtils;
    private final AliPayService alipayService;
    private final UserService userService;
    private final UserMapper userMapper;

    @ApiOperation("查询充值记录")
    @GetMapping
//    @AnonymousAccess
    @PreAuthorize("@el.check('recharge:list','admin')")
    public ResponseEntity<Object> queryMode(ReChargeQueryCriteria criteria, Pageable pageable){
        return new ResponseEntity<>(rechargeService.queryAll(criteria, pageable), HttpStatus.OK);
    }

    @ApiOperation("查询充值记录")
    @GetMapping(value = "web")
//    @AnonymousAccess
    @PreAuthorize("@el.check('recharge:weblist','admin')")
    public ResponseEntity<Object> queryModeWeb(ReChargeQueryCriteria criteria, Pageable pageable){
        Pageable pageable1 = PageRequest.of(pageable.getPageNumber()-1,pageable.getPageSize(),pageable.getSort());
        return new ResponseEntity<>(rechargeService.queryAll(criteria, pageable1), HttpStatus.OK);
    }

    @Log("新增充值记录")
    @ApiOperation("新增充值记录")
    @PostMapping
    @PreAuthorize("@el.check('recharge:add','admin')")
    public ResponseEntity<Object> createRecharge(@Validated @RequestBody Recharge resources){
        if (resources.getId() != null) {
            throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
        }
        rechargeService.create(resources);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @Log("支付宝PC网页充值")
    @ApiOperation("PC网页充值")
    @PostMapping(value = "/toPayAsPC")
    @PreAuthorize("@el.check('recharge:toPayAsPC','admin')")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<String> toPayAsPc(@Validated @RequestBody TradeVo trade) throws Exception {

        AlipayConfig aliPay = alipayService.find();

        //查询是否有待确认的充值记录
        List<Recharge> rechargelist = rechargeService.findByUsersIdAndStatus(SecurityUtils.getCurrentUserId(),2);
        if (rechargelist != null) {
//            throw new BadRequestException("您有一笔待确认的充值记录，请稍后再试");
            //将原来的充值记录改为失败
            for (Recharge recharge : rechargelist) {
                recharge.setRechargeState(1);
                rechargeService.update(recharge);
            }
        }
        trade.setOutTradeNo(alipayUtils.getOrderCode());
        String payUrl = alipayService.toPayAsPc(aliPay, trade);
        //初始化充值订单
        Recharge recharge = new Recharge();
        recharge.setRechargeType("支付宝支付");
        recharge.setBalance(Double.valueOf(trade.getTotalAmount()));
        recharge.setDetail(trade.getBody());
        recharge.setOutTradeNo(trade.getOutTradeNo());
        recharge.setRechargeState(2); //初始为等待确认
        recharge.setUser(userMapper.toEntity(userService.findById(SecurityUtils.getCurrentUserId())));
        recharge.setTime(new Date());
        rechargeService.create(recharge);
        return ResponseEntity.ok(payUrl);
    }

    @ApiIgnore
    @AnonymousGetMapping("/return")
    @ApiOperation("支付之后跳转的链接")
    public ResponseEntity<String> returnPage(HttpServletRequest request, HttpServletResponse response) {
        AlipayConfig alipay = alipayService.find();
        response.setContentType("text/html;charset=" + alipay.getCharset());
        //内容验签，防止黑客篡改参数
        try {
            if (alipayUtils.rsaCheck(request, alipay)) {
                //商户订单号
                String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                //支付宝交易号
                String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                System.out.println("商户订单号" + outTradeNo + "  " + "第三方交易号" + tradeNo);
                String totalAmount = new String(request.getParameter("total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                // 根据业务需要返回数据，这里统一返回OK
//                rechargeService.paySuccess(outTradeNo,tradeNo);
                rechargeService.paySuccessAfterNotify(outTradeNo,tradeNo,totalAmount);

                return new ResponseEntity<>("支付成功，请返回！", HttpStatus.OK);
            } else {
                // 根据业务需要返回数据
                //获取当前用户的上一次充值记录，支付失败
                List<Recharge> rechargelist = rechargeService.findByUsersIdAndStatus(SecurityUtils.getCurrentUserId(),2);
                if (rechargelist != null) {
                    for (Recharge recharge : rechargelist) {
                        recharge.setRechargeState(1);
                        rechargeService.update(recharge);
                    }
                }
                return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
            }
        }catch (Exception e){
            e.printStackTrace();
            // 根据业务需要返回数据
            //获取当前用户的上一次充值记录，支付失败
            List<Recharge> rechargelist = rechargeService.findByUsersIdAndStatus(SecurityUtils.getCurrentUserId(),2);
            if (rechargelist != null) {
                for (Recharge recharge : rechargelist) {
                    recharge.setRechargeState(1);
                    rechargeService.update(recharge);
                }
            }
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

    }

    @ApiIgnore
    @RequestMapping("/notify")
    @AnonymousAccess
    @ApiOperation("支付异步通知(要公网访问)，接收异步通知，检查通知内容app_id、out_trade_no、total_amount是否与请求中的一致，根据trade_status进行后续业务处理")
    public ResponseEntity<Object> notify(HttpServletRequest request) {
        AlipayConfig alipay = alipayService.find();
        Map<String, String[]> parameterMap = request.getParameterMap();
        //内容验签，防止黑客篡改参数
        if (alipayUtils.rsaCheck(request, alipay)) {
            //交易状态
            String tradeStatus = new String(request.getParameter("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            // 商户订单号
            String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            //支付宝交易号
            String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            //付款金额
            String totalAmount = new String(request.getParameter("total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            //验证
            if (tradeStatus.equals(AliPayStatusEnum.SUCCESS.getValue()) || tradeStatus.equals(AliPayStatusEnum.FINISHED.getValue())) {
                // 验证通过后应该根据业务需要处理订单
                rechargeService.paySuccessAfterNotify(outTradeNo,tradeNo,totalAmount);
            }else{ //交易失败
                rechargeService.payFailAfterNotify(outTradeNo,tradeNo,totalAmount);
            }
            return new ResponseEntity<>("success",HttpStatus.OK);
        }
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    }

    @PostMapping(value = "/checkTradeNo")
    @AnonymousAccess
    public ResponseEntity<Object> notify(@RequestBody JSONObject jsonObject) {
        String outTradeNo = jsonObject.getString("outTradeNo");
        AlipayTradeQueryRequest alipayTradeQueryRequest=new AlipayTradeQueryRequest();
        alipayTradeQueryRequest.setBizContent("{\"out_trade_no\":\" "+outTradeNo+"\"}");
        AlipayTradeQueryResponse response=null;
        try {
            AlipayConfig alipay = alipayService.find();
            AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppId(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
            response = alipayClient.execute(alipayTradeQueryRequest);
            System.out.println(response.getSubMsg());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return new ResponseEntity<>("success",HttpStatus.OK);
    }
}
